package com.CmJava.service.imp;

import com.CmJava.entity.ResultEntity;
import com.CmJava.entity.blog.Blog;
import com.CmJava.entity.blog.BlogModel;
import com.CmJava.entity.blog.BlogRedis;
import com.CmJava.entity.comment.CommentMysqlForBlog;
import com.CmJava.entity.project.ChildModel;
import com.CmJava.mapper.BlogCommentMapper;
import com.CmJava.mapper.BlogMapper;
import com.CmJava.service.BlogService;
import com.CmJava.utils.BackupUtil;
import com.CmJava.utils.OldBlogParseUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


@Service
public class BlogServiceImpl implements BlogService {

    @Autowired
    private BlogMapper blogMapper;

    @Autowired
    private BlogCommentMapper blogCommentMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    public ResultEntity getBlogList(String keyWord, String currentPage, int pageNum) {
        Page<Blog> page = new Page<>(Integer.parseInt(currentPage), pageNum);
        QueryWrapper<Blog> blogQueryWrapper = new QueryWrapper<>();
        if (keyWord.equals("")) {
            blogQueryWrapper.select("*");
        } else {
            blogQueryWrapper.like("blogTitle", keyWord);
        }
        Page<Blog> pageResult = (Page<Blog>) blogMapper.selectPage(page, blogQueryWrapper);
        if (pageResult == null) {
            return ResultEntity.failureWithoutMessage();
        }
        return ResultEntity.successWithMessage(pageResult);
    }

    @Override
    public ResultEntity getRecentBlog(int i, int i1) {
        QueryWrapper<Blog> blogQueryWrapper = new QueryWrapper<>();
        blogQueryWrapper.select("*");
        int blogNum = blogMapper.selectCount(blogQueryWrapper);
        if (blogNum == 0) {
            return ResultEntity.failureWithMessage("目前还没写过博客...");
        }
        blogQueryWrapper.last("LIMIT " + (blogNum - 5) + ",5");
        List<Blog> blogs = blogMapper.selectList(blogQueryWrapper);
        if (blogs != null && blogs.size() > 0) {
            return ResultEntity.successWithMessage(blogs);
        }
        return ResultEntity.failureWithoutMessage();
    }

    @Override
    public ResultEntity getNewBlogId() {
        QueryWrapper<Blog> blogQueryWrapper = new QueryWrapper<>();
        blogQueryWrapper.select("*");
        int blogNum = blogMapper.selectCount(blogQueryWrapper);
        return ResultEntity.successWithMessage(blogNum + 1);
    }

    @Override
    public ResultEntity addBlogRedis(String key, String blogRedisData) {
        redisTemplate.opsForValue().set(key, blogRedisData);
        return ResultEntity.successWithoutMessage();
    }

    @Override
    public ResultEntity addBlogMysql(Blog blog) {
        Blog exitBlog = blogMapper.selectById(blog.getId());
        if (exitBlog == null) {
            //添加博客
            int insert = blogMapper.insert(blog);
            if (insert != 1) {
                return ResultEntity.failureWithoutMessage();
            }
            return ResultEntity.successWithoutMessage();
        } else {
            //更新博客
            int update = blogMapper.updateById(blog);
            if (update != 1) {
                return ResultEntity.failureWithoutMessage();
            }
            return ResultEntity.successWithoutMessage();
        }
    }

    @Override
    public ResultEntity getBlogMysql(String blogId) {
        Blog blog = blogMapper.selectById(blogId);
        if (blog != null) {
            return ResultEntity.successWithMessage(blog);
        }
        return ResultEntity.failureWithoutMessage();
    }

    @Override
    public ResultEntity getBlogRedis(String key) {
        ResultEntity resultEntity = dispatchBlog(key);
        return resultEntity;
    }

    //分发新旧博客以适应新博客系统
    private ResultEntity dispatchBlog(String key) {
        Integer blogId = Integer.parseInt(key.split("_")[0].substring(4));
        if (blogId >= 57) {
            ResultEntity resultEntity = getNewBlog(key);
            return resultEntity;
        } else {
            ResultEntity resultEntity = getOldBlog(key);
            return resultEntity;
        }
    }

    //获取新博客
    private ResultEntity getNewBlog(String key) {
        if (redisTemplate.hasKey(key)) {
            String blogRedisData = (String) redisTemplate.opsForValue().get(key);
            return ResultEntity.successWithMessage(blogRedisData);
        } else {
            return ResultEntity.failureWithoutMessage();
        }
    }

    //获取旧博客
    private ResultEntity getOldBlog(String key) {
        if (redisTemplate.hasKey(key)) {
            BlogRedis blogRedis = null;
            String blogRedisData = "";
            try {
                blogRedis = (BlogRedis) redisTemplate.opsForValue().get(key);
                blogRedisData = OldBlogParseUtil.parseOldBlog(blogRedis);
            } catch (ClassCastException e) {
                //转换失败说明已经被转成新博客的格式了
                return getNewBlog(key);
            }

            //转换完毕存回去
            redisTemplate.opsForValue().set(key, blogRedisData);

            return ResultEntity.successWithMessage(blogRedisData);
        } else {
            return ResultEntity.failureWithoutMessage();
        }
    }

    @Override
    public ResultEntity getBlogModelAndChildNum(String key) {
        if (redisTemplate.hasKey(key)) {
            BlogRedis blogRedis = (BlogRedis) redisTemplate.opsForValue().get(key);
            ArrayList<Integer> list = new ArrayList<>();
            int modelNum = blogRedis.getModel().size();
            list.add(modelNum);
            for (int i = 0; i < modelNum; i++) {
                int childNum = blogRedis.getModel().get(i).getChildModel().size();
                list.add(childNum);
            }
            return ResultEntity.successWithMessage(list);
        } else {
            return ResultEntity.failureWithoutMessage();
        }
    }

    @Override
    public ResultEntity updateBlogMysql(Blog blog) {
        int i = blogMapper.updateById(blog);
        if (i == 1) {
            return ResultEntity.successWithoutMessage();
        }
        return ResultEntity.failureWithoutMessage();
    }

    @Override
    public ResultEntity updateThisBlogModle(String key, String modelId, BlogModel blogModel) {
        if (redisTemplate.hasKey(key)) {
            BlogRedis blogRedis = (BlogRedis) redisTemplate.opsForValue().get(key);
            List<BlogModel> model = blogRedis.getModel();
            model.set(Integer.parseInt(modelId) - 1, blogModel);
            redisTemplate.opsForValue().set(key, blogRedis);
            return ResultEntity.successWithMessage(blogRedis);
        } else {
            return ResultEntity.failureWithoutMessage();
        }
    }

    @Override
    public ResultEntity getAdminBlogList() {
        QueryWrapper<Blog> blogQueryWrapper = new QueryWrapper<>();
        blogQueryWrapper.select("id", "blogTitle", "visitNum");
        List<Blog> blogs = blogMapper.selectList(blogQueryWrapper);
        //倒序
        Collections.reverse(blogs);

        return ResultEntity.successWithMessage(blogs);
    }

    @Override
    public ResultEntity addBlogCommentMysql(String blogId) {
        QueryWrapper<CommentMysqlForBlog> commentMysqlForBlogQueryWrapper = new QueryWrapper<>();
        commentMysqlForBlogQueryWrapper.select("*");
        int id = blogCommentMapper.selectCount(commentMysqlForBlogQueryWrapper);
        if (id > 0) {
            int insert = blogCommentMapper.insert(new CommentMysqlForBlog(id + 1, Integer.parseInt(blogId), 0, "--"));
            if (insert != 1) {
                return ResultEntity.failureWithoutMessage();
            }
            return ResultEntity.successWithoutMessage();
        } else {
            int insert = blogCommentMapper.insert(new CommentMysqlForBlog(1, Integer.parseInt(blogId), 0, "--"));
            if (insert != 1) {
                return ResultEntity.failureWithoutMessage();
            }
            return ResultEntity.successWithoutMessage();
        }
    }

    @Override
    public void blogVisitNumIncrement(String blogId) {

        Blog blog = blogMapper.selectById(blogId);
        blog.setVisitNum(blog.getVisitNum() + 1);

        blogMapper.updateById(blog);


    }

    @Override
    public ResultEntity deleteBlogModel(String blogId, int modelIndex) {
        String key = "blog" + blogId + "_for_MyWeb";

        if (redisTemplate.hasKey(key)) {
            BlogRedis blogRedis = (BlogRedis) redisTemplate.opsForValue().get(key);
            blogRedis.getModel().remove(modelIndex);

            redisTemplate.opsForValue().set(key, blogRedis);

            return ResultEntity.successWithoutMessage();
        }


        return ResultEntity.failureWithoutMessage();
    }

    @Override
    public ResultEntity deleteBlogChildModel(String blogId, int modelIndex, int childIndex) {
        String key = "blog" + blogId + "_for_MyWeb";

        if (redisTemplate.hasKey(key)) {
            BlogRedis blogRedis = (BlogRedis) redisTemplate.opsForValue().get(key);
            BlogModel blogModel = blogRedis.getModel().get(modelIndex);
            blogModel.getChildModel().remove(childIndex);

            redisTemplate.opsForValue().set(key, blogRedis);

            return ResultEntity.successWithoutMessage();
        }
        return ResultEntity.failureWithoutMessage();
    }

    @Override
    public ResultEntity backupBlog(String blogId) {
        String key = "blog" + blogId + "_for_MyWeb";

        //备份redis
        ResultEntity resultEntity = dispatchBlog(key);
        if (resultEntity.getResultFlag()) {
            return BackupUtil.backupTheBlog(key, resultEntity.getData());
        }
        return ResultEntity.failureWithMessage("备份博客(" + key + ")失败，数据库内未找到该篇博客");
    }

    @Override
    public ResultEntity downBackupBlog() {
        return BackupUtil.downBackupBlogs();
    }
}
